package define

import (
	"encoding/json"
	"fmt"
	"strings"
)

const (
	AgentStateReady    = "Ready"
	AgentStateNotReady = "NotReady"
	AgentStateUnKnow   = "UnKnown"
)

type Tag struct {
	Key   string `json:"key" yaml:"key"`
	Type  string `json:"type" yaml:"type"`
	Value string `json:"value" yaml:"value"`
}

func (r *Tag) ToString() string {
	return fmt.Sprintf("%v|%v|%v", r.Key, r.Type, r.Value)
}

func (r *Tag) FromString(tStr string) error {
	res := strings.Split(tStr, "|")
	if len(res) != 3 {
		return fmt.Errorf("unkown tag string")
	}
	r.Key, r.Type, r.Value = res[0], res[1], res[2]
	return nil
}

func DefaultAgent() *AgentInfo {
	a := &AgentInfo{}

	a.BaseInfo.IP = "8.8.8.8"
	a.BaseInfo.MAC = "9e:08:02:f5:a9:68"

	a.SpecInfo.OS = "centos"
	a.SpecInfo.Arch = "x86"
	a.SpecInfo.Tags = []Tag{{Key: "model", Type: "string", Value: "test"}}

	a.Resource.MEM = fmt.Sprintf("%v", 1024*1024*1024)
	a.Resource.CPUs = fmt.Sprintf("%v", 1000*32)

	a.Instances = []string{}
	a.StatusInfo.Guid = ""
	a.StatusInfo.State = AgentStateNotReady

	return a
}

//TODO 暂定
type AgentInfo struct {
	BaseInfo   agentBaseInfo  `json:"base_info" yaml:"base_info"`
	StatusInfo agentStateInfo `json:"state" yaml:"state"`
	SpecInfo   agentSpecInfo  `json:"spec_info" yaml:"spec_info"`
	Resource   agentResource  `json:"resource" yaml:"resource"`
	Instances  []string       `json:"instances" yaml:"instances"`
}

type agentBaseInfo struct {
	IP  string `json:"ip_address" yaml:"ip_address"`
	MAC string `json:"mac_address" yaml:"mac_address"`
}

type agentStateInfo struct {
	State string `json:"state" yaml:"state"`
	Guid  string `json:"guid" yaml:"guid"`
}

type agentResource struct {
	CPUs string `json:"cpu_cores" yaml:"cpu_cores"`
	MEM  string `json:"memory_bytes" yaml:"memory_bytes"`
}

type agentSpecInfo struct {
	OS   string `json:"os" yaml:"os"`
	Arch string `json:"arch" yaml:"arch"`
	Tags []Tag  `json:"tags" yaml:"tags"`
}

func (r *agentSpecInfo) Clone() agentSpecInfo {
	tags := make([]Tag, len(r.Tags))
	for k, v := range r.Tags {
		tags[k] = v
	}
	return agentSpecInfo{
		OS:   r.OS,
		Arch: r.Arch,
		Tags: tags,
	}
}

func (r agentSpecInfo) EnCodeTags() string {
	bts, err := json.Marshal(r.Tags)
	if err != nil {
		panic(err)
	}
	return string(bts)
}
func (r agentSpecInfo) DeCodeTags(tags string) {
	if err := json.Unmarshal([]byte(tags), &r.Tags); err != nil {
		panic(err)
	}
}

func (r AgentInfo) EnCodeInstance() string {
	bts, err := json.Marshal(r.Instances)
	if err != nil {
		panic(err)
	}
	return string(bts)
}
func (r AgentInfo) DeCodeInstance(tags string) {
	if err := json.Unmarshal([]byte(tags), &r.Instances); err != nil {
		panic(err)
	}
}

func (r *AgentInfo) Clone() *AgentInfo {
	is := make([]string, len(r.Instances))
	for k, v := range r.Instances {
		is[k] = v
	}

	c := &AgentInfo{
		BaseInfo:   r.BaseInfo,
		StatusInfo: r.StatusInfo,
		SpecInfo:   r.SpecInfo.Clone(),
		Instances:  is,
	}
	return c
}

//type MetricAgentInfo struct {
//	TimeScale []time.Time            `json:"timeScale" yaml:"timeScale"`
//	Trace      map[string]interface{} `json:"data" yaml:"data"`
//}

//type MetricStatisticAgentInfo struct {
//	TimeScale []time.Time         `json:"timeScale" yaml:"timeScale"`
//	Trace      map[string][]string `json:"data" yaml:"data"`
//}

//func (r *MetricStatisticAgentInfo) Clone() *MetricStatisticAgentInfo {
//	c := &MetricStatisticAgentInfo{
//		TimeScale: r.TimeScale,
//		Trace:      r.Trace,
//	}
//	return c
//}
